package com.jroky.base.api;



import com.github.pagehelper.PageInfo;
import com.jroky.base.service.BaseService;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;


@Data
@Slf4j
public class BaseApi<M extends BaseService<T>, T> {

    @Autowired
    protected M baseService;

    /**
     * 泛型T的class
     */
    private Class<T> typeParameterClass;

    /**
     * 导出模板的文件名
     */
    protected String fileName = "模板文件";

    /**
     * 创建对象接口
     * 创建对象
     *
     * @param o
     * @return
     */
    @PostMapping
    public T create(@RequestBody @Validated T o) {
        baseService.save(o);
        return o;
    }

    /**
     * 全量导入
     *
     * @param request
     * @param response
     * @param entity
     */
    @PostMapping("/full/import")
    public void importByExcel(HttpServletRequest request, HttpServletResponse response, @Validated T entity) {
        MultipartFile file = null;
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        file = multipartRequest.getFile("file");
        if (null == file || StringUtils.isBlank(file.getOriginalFilename())) {
            throw new RuntimeException("文件为空");
        }
        this.baseService.fullImportByExcel(response, file, entity);
    }

    /**
     * 导出模板
     * @param request
     * @param response
     */
    @GetMapping("/export/template")
    public void exportTemplateExcel(HttpServletRequest request, HttpServletResponse response) {
        this.baseService.exportTemplateExcel(request,response, this.getFileName(), this.getTypeParameterClass());
    }

    /**
     * 根据id查询
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public T selectById(@PathVariable String id) {
        return  baseService.getByIdDeep(id);
    }

    /**
     * 根据id修改
     *
     * @param id
     * @param entity
     * @return
     */
    @PutMapping("/{id}")
    public T updateById(@PathVariable String id,@RequestBody @Validated T entity) {
        try {
            Field field = entity.getClass().getDeclaredField("id");
            field.setAccessible(true);
            field.set(entity,id);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        baseService.updateById(entity);
        return entity;
    }

    /**
     * 根据id删除
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public void updateById(@PathVariable String id) {
        baseService.removeById(id);
    }

    /**
     * 分页查询
     *
     * @param pageInfo
     * @param entity
     * @return
     */
    @GetMapping("/page")
    public PageInfo<T> pageList(PageInfo pageInfo, T entity) {
        return baseService.pageList(pageInfo,entity);
    }

    /**
     * 不分页查询
     *
     * @param entity
     */
    @GetMapping
    public List<T> dataList(T entity) {
        return baseService.dataList(entity);
    }

    public Class<T> getTypeParameterClass(){
        if (typeParameterClass == null){
            initTypeParameterClass();
        }
        
        return typeParameterClass;
    }

    /**
     * 获取当前实现类中的泛型T的实际类的CLass
     */
    protected void initTypeParameterClass() {
        Type type=getClass().getGenericSuperclass();

        if (type instanceof ParameterizedType){
            ParameterizedType parameterizedType=(ParameterizedType) type;
            Type[] types=parameterizedType.getActualTypeArguments();

            if (types.length>1 && types[1] instanceof Class){
                typeParameterClass = (Class<T>)  types[1];
            }
        }
    }
}